import * as THREE from "three";
import * as kokomi from "kokomi.js";
import gsap from "gsap";
import type Experience from "../Experience";

/**
 * 车身波浪线条组件
 * 长按车身时显示环绕车身的贝塞尔曲线动画
 * 曲线从外向内收缩，最终在车顶汇集
 */
export default class CarWaveLines extends kokomi.Component {
  declare base: Experience;
  linesGroup: THREE.Group;
  isAnimating: boolean = false;
  animationTimer: number | null = null;
  lines: THREE.Line[] = [];
  lineAnimations: any[] = [];

  constructor(base: Experience) {
    super(base);

    this.linesGroup = new THREE.Group();
    this.linesGroup.visible = false;
  }

  /**
   * 创建单条贝塞尔曲线（从上到下的等高线）
   * @param waveIndex 波浪索引，控制从上到下的位置
   * @param delay 延迟时间
   */
  createWaveLine(waveIndex: number, delay: number = 0) {
    // 创建环绕车身的贝塞尔曲线控制点
    const baseRadius = 5.6; // 基础半径（车身大小）
    const topHeight = 1.4; // 车顶高度
    const bottomHeight = -0.5; // 底部高度
    const heightStep = (topHeight - bottomHeight) / 18; // 每层高度间距
    const currentHeight = topHeight - waveIndex * heightStep; // 当前曲线高度
    
    // 根据高度调整半径（越往下半径越大，模拟车身形状）
    const heightRatio = (topHeight - currentHeight) / (topHeight - bottomHeight);
    const radiusMultiplier = 0.3 + heightRatio * 0.7; // 从0.3到1.0
    const currentRadius = baseRadius * radiusMultiplier;

    // 创建曲线的控制点（环绕车身一周）
    const points: THREE.Vector3[] = [];
    const segments = 64; // 曲线分段数

    // 创建环形曲线路径（水平切片）
    for (let i = 0; i <= segments; i++) {
      const t = i / segments;
      const angle = t * Math.PI * 2;
      
      // 使用椭圆形状模拟车身轮廓
      const x = Math.cos(angle) * currentRadius * 1.2; // 长度方向
      const z = Math.sin(angle) * currentRadius * 0.6; // 宽度方向
      const y = currentHeight; // 当前层的高度
      
      points.push(new THREE.Vector3(x, y, z));
    }

    // 创建平滑的Catmull-Rom曲线
    const curve = new THREE.CatmullRomCurve3(points, true); // true表示闭合曲线
    const curvePoints = curve.getPoints(200); // 获取更多点以获得平滑效果

    // 创建几何体和材质
    const geometry = new THREE.BufferGeometry().setFromPoints(curvePoints);
    const material = new THREE.LineBasicMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 0,
      linewidth: 2,
    });

    const line = new THREE.Line(geometry, material);
    this.linesGroup.add(line);
    this.lines.push(line);

    // 设置初始透明度为0
    material.opacity = 0;
    
    // 动画数据 - 只有波动效果
    const animData = {
      wavePhase: 0, // 波动相位
      opacity: 0,
    };

    // 动画序列：淡入 + 持续波动
    const tl = gsap.timeline({ delay });
    
    // 第一阶段：淡入
    tl.to(animData, {
      opacity: 0.5,
      duration: 0.3,
      ease: "power2.out",
      onUpdate: () => {
        material.opacity = animData.opacity;
      },
    });

    this.lineAnimations.push(tl);
    
    // 持续波动动画（无限循环）- 从下到上的波动效果
    // 底部曲线先开始波动（waveIndex越大，越靠下，延迟越小）
    const waveDelay = delay + 0.3 + (20 - waveIndex) * 0.05;
    
    const waveTl = gsap.timeline({ 
      delay: waveDelay,
      repeat: -1, // 无限循环
    });
    
    waveTl.to(animData, {
      wavePhase: Math.PI * 2,
      duration: 2.5,
      ease: "none",
      onUpdate: () => {
        this.updateLineWave(line, waveIndex, animData.wavePhase);
      },
    });

    this.lineAnimations.push(waveTl);
  }

  /**
   * 更新曲线波动效果
   */
  updateLineWave(line: THREE.Line, waveIndex: number, wavePhase: number) {
    const baseRadius = 4.6;
    const topHeight = 1.4;
    const bottomHeight = -0.5;
    const heightStep = (topHeight - bottomHeight) / 20;
    const currentHeight = topHeight - waveIndex * heightStep;
    
    // 根据高度调整半径
    const heightRatio = (topHeight - currentHeight) / (topHeight - bottomHeight);
    const radiusMultiplier = 0.3 + heightRatio * 0.7;
    const baseCurrentRadius = baseRadius * radiusMultiplier;
    
    const waveAmplitude = 0.3; // 波动幅度
    const points: THREE.Vector3[] = [];
    const segments = 64;

    for (let i = 0; i <= segments; i++) {
      const t = i / segments;
      const angle = t * Math.PI * 2;
      
      // 添加波动效果：正弦波沿着曲线传播
      const wave = Math.sin(angle * 3 + wavePhase) * waveAmplitude;
      const currentRadius = baseCurrentRadius + wave;
      
      const x = Math.cos(angle) * currentRadius * 1.2;
      const z = Math.sin(angle) * currentRadius * 0.6;
      
      // 添加垂直方向的轻微波动
      const heightWave = Math.sin(angle * 2 + wavePhase * 0.7) * 0.05;
      const y = currentHeight + heightWave;
      
      points.push(new THREE.Vector3(x, y, z));
    }

    const curve = new THREE.CatmullRomCurve3(points, true);
    const curvePoints = curve.getPoints(200);
    
    const geometry = line.geometry as THREE.BufferGeometry;
    geometry.setFromPoints(curvePoints);
  }

  /**
   * 开始动画（从上到下逐层显示）
   */
  start() {
    if (this.isAnimating) return;

    this.isAnimating = true;
    this.linesGroup.visible = true;

    // 创建多条从上到下的曲线（15条，覆盖整个车身高度）
    const totalLines = 20;
    for (let i = 0; i < totalLines; i++) {
      // 从上到下逐层显示，每条延迟时间递增
      const delay = i * 0.02;
      this.createWaveLine(i, delay);
    }
  }

  /**
   * 停止动画（淡出效果）
   */
  stop() {
    if (!this.isAnimating) return;

    this.isAnimating = false;

    // 清除定时器
    if (this.animationTimer) {
      clearTimeout(this.animationTimer);
      this.animationTimer = null;
    }

    // 淡出所有曲线
    this.lines.forEach((line, index) => {
      gsap.to((line.material as THREE.LineBasicMaterial), {
        opacity: 0,
        duration: 0.5,
        delay: index * 0.05,
        onComplete: () => {
          this.linesGroup.remove(line);
          line.geometry.dispose();
          (line.material as THREE.Material).dispose();
        },
      });
    });

    // 停止所有正在进行的动画
    this.lineAnimations.forEach(tl => {
      tl.kill();
    });
    this.lineAnimations = [];
    this.lines = [];

    // 延迟隐藏组
    setTimeout(() => {
      this.linesGroup.visible = false;
    }, 1000);
  }

  /**
   * 添加到场景
   */
  addExisting() {
    this.container.add(this.linesGroup);
  }

  /**
   * 销毁组件
   */
  destroy() {
    this.stop();
    this.linesGroup.clear();
  }
}
